# -*- coding: utf-8 -*-
# Copyright (c) 2010 Andrei Antoukh <niwi@niwi.be>
# Including code based on «python-bicing»

from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app


from django.utils import simplejson as json
from xml.dom import minidom
from database import *

import re, os ,urllib2, datetime

URL = 'http://bicing.cat/localizaciones/localizaciones.php'
XML_RE = re.compile(r"exml.parseString\('(.*)'\);")
template_path = os.path.join(os.path.dirname(__file__), 'templates')

class Bicing(webapp.RequestHandler):
  """ Pagina principal con ayuda para el uso de las api. """

  def get(self):
    self.response.out.write(template.render(
      os.path.join(template_path, "bicing.html"), {}))


class BicingApiAll(webapp.RequestHandler):
  """ Handler para visualizar todos los datos. """

  _indent = -1
  _format = 'json'

  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    if self.request.GET.has_key("indent"):
      self._indent = int(self.request.get('indent'))
      
    if self.request.GET.has_key("format"):
      self._format = self.request.get('format')
      if self._format not in ['json','xml']:
        self._format = 'json'
        
    query = NStation.all().order("stid")
    stations = []
    for st in query:
      stations.append(st.to_dict())
    
    buffer = "[]"
    if self._format == 'json':
      if self._indent > 0:
        buffer = json.dumps(stations, indent=self._indent)
      else:
        buffer = json.dumps(stations)
    
    elif self._format == 'xml':
      buffer = template.render(os.path.join(template_path, "stations.xml"), {'stations': stations })

    self.response.out.write(buffer)

class BicingApiOne(webapp.RequestHandler):
  """ Handler para obtener datos de una sola estacion mediante
  su identificacion. """
  
  _indent = -1
  _format = 'json'

  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    
    if self.request.GET.has_key("indent"):
      self._indent = int(self.request.get('indent'))

    if self.request.GET.has_key("format"):
      self._format = self.request.get('format')
      if self._format not in ['json','xml']:
        self._format = 'json'
    
    buffer = "{}"
    if self.request.GET.has_key('id'):
      stid = int(self.request.get('id'))
      query = NStation.gql("WHERE stid = :1", stid)
      nst = query.get()
      if nst != None:
        if self._format == 'json':
          if self._indent > 0:
            buffer = json.dumps(nst.to_dict(), indent=self._indent)
          else:
            buffer = json.dumps(nst.to_dict())
        
        elif self._format == 'xml':
          buffer = template.render(os.path.join(template_path, "station.xml"), {'station':nst})
    
    self.response.out.write(buffer)

class BicingApiIdList(webapp.RequestHandler):
  """ Handler para obtener una lista de ids y sus correspondientes nombres
  de estaciones. """

  _indent = -1
  _format = 'json'

  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    
    if self.request.GET.has_key("indent"):
      self._indent = int(self.request.get('indent'))

    if self.request.GET.has_key("format"):
      self._format = self.request.get('format')
      if self._format not in ['json','xml']:
        self._format = 'json'

    query = NStation.all().order("stid")
    ids = []
    
    for st in query:
      ids.append({'id':st.stid, 'name':st.name})
    
    buffer = "[]"
    if self._format == 'json':
      if self._indent > 0:
        buffer = json.dumps(ids, indent=self._indent)
      else:
        buffer = json.dumps(ids)
    
    elif self._format == 'xml':
      buffer = template.render(os.path.join(template_path, "list.xml"), {'stations': ids })

    self.response.out.write(buffer)


# Code based on python-bicing
class BicingWorker(webapp.RequestHandler):
  """ Handler para realizar una actualizacion de los datos mediante 
  tareas programadas (cron). """

  _tsformat = '%Y-%m-%d %H:%M:%S'
  
  def get(self):
    self.response.headers['Content-Type'] = 'text/html'
    try:
      page = urllib2.urlopen(URL)
      date = page.info()['Date']

      date_format = '%a, %d %b %Y %H:%M:%S %Z'
      timestamp = datetime.datetime.strptime(date, date_format)
      content = page.read()
      page.close()
    
      xml = XML_RE.search(content).groups()[0]
      dom = minidom.parseString(xml.decode('iso-8859-15').encode('utf-8'))
    
      placemarks = dom.getElementsByTagName('Placemark')
      stations = []
      for index, placemark in enumerate(placemarks):
        xml_buff = placemark.getElementsByTagName('description')[0].firstChild.nodeValue
        stid = int(minidom.parseString(xml_buff.encode('utf-8')).firstChild.getElementsByTagName('div')[0].firstChild.nodeValue.split(" - ")[0])
        query = NStation.gql("WHERE stid = :1", stid)
        station = query.get()
        if station == None:
          station = NStation()
          station.from_xml(placemark)
          station.lastupdate = unicode(timestamp)
          station.put()
        else:
          station.from_xml(placemark)
          station.lastupdate = unicode(timestamp)
          station.put()

      self.response.out.write("1")
    except:
      self.response.out.write("0")


urls = [
  ('/', Bicing),
  ('/api/all', BicingApiAll),
  ('/api/one', BicingApiOne),
  ('/api/list', BicingApiIdList),
  ('/run', BicingWorker),
]

application = webapp.WSGIApplication(urls, debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()
